package io.summer.basis.tool;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Moonlight
 */
@Component
public final class ObjectTool {
  private static ObjectMapper objectMapper;
  private static final Logger log = LoggerFactory.getLogger(ObjectTool.class);

  public ObjectTool(ObjectMapper mapper) {
    objectMapper = mapper;
  }

  public static ObjectMapper mapper() {
    return objectMapper;
  }

  private static final Map<Type, JavaType> TYPE_CACHE = new ConcurrentHashMap<>();

  private static JavaType jacksonType(Type type) {
    return TYPE_CACHE.computeIfAbsent(type, k -> objectMapper.getTypeFactory().constructType(type));
  }

  public static byte[] serialize(Object o) {
    try {
      return objectMapper.writeValueAsBytes(o);
    } catch (JsonProcessingException e) {
      log.error("serialize error: ", e);
    }
    return new byte[0];
  }

  @SuppressWarnings("unchecked")
  public static <T> T deserialize(@NonNull byte[] s, Type dataType) {
    T data = null;
    try {
      data = objectMapper.readValue(s, jacksonType(dataType));
    } catch (IOException e) {
      log.error("deserialize error: ", e);
    }
    return data;
  }
}
